package ir;

import run.Cell;
import run.core.INITIAL;
import run.core.INT;
import run.core.NEGATE;
import run.core.STRLIT;
import run.core.StrCell;

/**
 * An IR class representing the Cell unit.
 * @author Thomas Chau
 *
 */
public class CellUnit {

	// the type of cell
	protected String cellTypeName;
	
	// the label (if any) used by programmer for this instance
	protected String labelName;

	// the actual object in memory that this IR is supposed to resolve to
	private Cell underlying_cell;
	
	public CellUnit(String typeName) {
		cellTypeName = typeName;
		labelName = null;
	}
	
	public Cell genesis(StructuralDefinition d) {
		if (cellTypeName.equals("STR"))
			underlying_cell = new StrCell(labelName);
		else if (cellTypeName.equals("INT"))
			underlying_cell = new INT(labelName);
		else if (cellTypeName.equals("INITIAL"))
			underlying_cell = new INITIAL(labelName);
		else if (cellTypeName.equals("STRLIT"))
			underlying_cell = new STRLIT(labelName);
		else if (cellTypeName.equals("NEGATE"))
			underlying_cell = new NEGATE(labelName);
		else if (cellTypeName.equals("MEM"))
			underlying_cell = new run.core.MEM(labelName);
		else if (cellTypeName.equals("GREATER_THAN"))
			underlying_cell = new run.core.GREATER_THAN(labelName);
		else if (cellTypeName.equals("LESS_THAN"))
			underlying_cell = new run.core.LESS_THAN(labelName);
		else if (cellTypeName.equals("EQUALS"))
			underlying_cell = new run.core.EQUALS(labelName);
		else if (cellTypeName.equals("ADD"))
			underlying_cell = new run.core.ADD(labelName);
		else if (cellTypeName.equals("SOUT"))
			underlying_cell = new run.core.SOUT(labelName);
		else if (cellTypeName.equals("GUI"))
			underlying_cell = new run.core.GUI(labelName);
		else
			try { underlying_cell = (Cell)Class.forName("run.core." + cellTypeName).newInstance(); }
			catch (Exception e) { underlying_cell = null; }
			
			// else, may be a user cell
		if (underlying_cell == null) {
			CellDef cellDef = CellLib.getInstance().getCellDef(cellTypeName);
			underlying_cell = cellDef.realize();
			underlying_cell.setLabelName(labelName);
			if (underlying_cell == null) {
				System.out.println("ERROR: UNIMPLEMENTED CELL: " + cellTypeName);
			}
		}
		
		return underlying_cell;
	}
	
	/**
	 * Label alias used by programmer.
	 * @param label
	 */
	public void setLabelName(String label) {
		labelName = label;
	}

	/**
	 * This is where you instantiate stuff such as your core cells,
	 * e.g. return new Sout();
	 * in the case that the cellTypeName is 'Sout'
	 */
	public Cell getUnderlyingObject(StructuralDefinition d) {
		if (underlying_cell == null) {
			underlying_cell = genesis(d);
		}
			
		return underlying_cell;
	}
	
	public String getLabel() {
		return labelName;
	}
	
	public String toString() {
		if (labelName != null)
			return labelName;
		return cellTypeName;
	}
	
	public CellUnit clone() {
		CellUnit cellUnit = new CellUnit(cellTypeName);
		cellUnit.setLabelName(labelName);
		return cellUnit;
	}

}
